home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gdevm24.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  15.3 KB  |  602 lines

  1. /* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gdevm24.c,v 1.2 2000/09/19 19:00:13 lpd Exp $ */
  20. /* 24-bit-per-pixel "memory" (stored bitmap) device */
  21. #include "memory_.h"
  22. #include "gx.h"
  23. #include "gxdevice.h"
  24. #include "gxdevmem.h"        /* semi-public definitions */
  25. #include "gdevmem.h"        /* private definitions */
  26.  
  27. #define mem_true24_strip_copy_rop mem_gray8_rgb24_strip_copy_rop
  28.  
  29. /*
  30.  * Define whether to use the library's memset.
  31.  */
  32. /*#define USE_MEMSET*/
  33. /*
  34.  * Define whether to use memcpy for very wide fills.  We thought this
  35.  * made a big difference, but it turned out to be an artifact of the
  36.  * profiler.
  37.  */
  38. /*#define USE_MEMCPY*/
  39.  
  40. /* Define debugging statistics. */
  41. #ifdef DEBUG
  42. struct stats_mem24_s {
  43.     long
  44.     fill, fwide, fgray[101], fsetc, fcolor[101], fnarrow[5],
  45.     fprevc[257];
  46.     double ftotal;
  47. } stats_mem24;
  48. static int prev_count;
  49. static uint prev_colors[256];
  50. # define INCR(v) (++(stats_mem24.v))
  51. #else
  52. # define INCR(v) DO_NOTHING
  53. #endif
  54.  
  55.  
  56. /* ================ Standard (byte-oriented) device ================ */
  57.  
  58. #undef chunk
  59. #define chunk byte
  60.  
  61. /* Procedures */
  62. declare_mem_procs(mem_true24_copy_mono, mem_true24_copy_color, mem_true24_fill_rectangle);
  63. private dev_proc_copy_alpha(mem_true24_copy_alpha);
  64.  
  65. /* The device descriptor. */
  66. const gx_device_memory mem_true24_device =
  67. mem_full_alpha_device("image24", 24, 0, mem_open,
  68.          gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
  69.      mem_true24_copy_mono, mem_true24_copy_color, mem_true24_fill_rectangle,
  70.               gx_default_map_cmyk_color, mem_true24_copy_alpha,
  71.          gx_default_strip_tile_rectangle, mem_true24_strip_copy_rop,
  72.               mem_get_bits_rectangle);
  73.  
  74. /* Convert x coordinate to byte offset in scan line. */
  75. #undef x_to_byte
  76. #define x_to_byte(x) ((x) * 3)
  77.  
  78. /* Unpack a color into its bytes. */
  79. #define declare_unpack_color(r, g, b, color)\
  80.     byte r = (byte)(color >> 16);\
  81.     byte g = (byte)((uint)color >> 8);\
  82.     byte b = (byte)color
  83. /* Put a 24-bit color into the bitmap. */
  84. #define put3(ptr, r, g, b)\
  85.     (ptr)[0] = r, (ptr)[1] = g, (ptr)[2] = b
  86. /* Put 4 bytes of color into the bitmap. */
  87. #define putw(ptr, wxyz)\
  88.     *(bits32 *)(ptr) = (wxyz)
  89. /* Load the 3-word 24-bit-color cache. */
  90. /* Free variables: [m]dev, rgbr, gbrg, brgb. */
  91. #if arch_is_big_endian
  92. #  define set_color24_cache(crgb, r, g, b)\
  93.     mdev->color24.rgbr = rgbr = ((bits32)(crgb) << 8) | (r),\
  94.     mdev->color24.gbrg = gbrg = (rgbr << 8) | (g),\
  95.     mdev->color24.brgb = brgb = (gbrg << 8) | (b),\
  96.     mdev->color24.rgb = (crgb)
  97. #else
  98. #  define set_color24_cache(crgb, r, g, b)\
  99.     mdev->color24.rgbr = rgbr =\
  100.         ((bits32)(r) << 24) | ((bits32)(b) << 16) |\
  101.         ((bits16)(g) << 8) | (r),\
  102.     mdev->color24.brgb = brgb = (rgbr << 8) | (b),\
  103.     mdev->color24.gbrg = gbrg = (brgb << 8) | (g),\
  104.     mdev->color24.rgb = (crgb)
  105. #endif
  106.  
  107. /* Fill a rectangle with a color. */
  108. private int
  109. mem_true24_fill_rectangle(gx_device * dev,
  110.               int x, int y, int w, int h, gx_color_index color)
  111. {
  112.     gx_device_memory * const mdev = (gx_device_memory *)dev;
  113.     declare_unpack_color(r, g, b, color);
  114.     declare_scan_ptr(dest);
  115.  
  116.     /*
  117.      * In order to avoid testing w > 0 and h > 0 twice, we defer
  118.      * executing setup_rect, and use fit_fill_xywh instead of
  119.      * fit_fill.
  120.      */
  121.     fit_fill_xywh(dev, x, y, w, h);
  122.     INCR(fill);
  123. #ifdef DEBUG
  124.     stats_mem24.ftotal += w;
  125. #endif
  126.     if (w >= 5) {
  127.     if (h <= 0)
  128.         return 0;
  129.     INCR(fwide);
  130.     setup_rect(dest);
  131.     if (r == g && r == b) {
  132. #ifndef USE_MEMSET
  133.         /* We think we can do better than the library's memset.... */
  134.         int bcntm7 = w * 3 - 7;
  135.         register bits32 cword = color | (color << 24);
  136.  
  137.         INCR(fgray[min(w, 100)]);
  138.         while (h-- > 0) {
  139.         register byte *pptr = dest;
  140.         byte *limit = pptr + bcntm7;
  141.  
  142.         /* We want to store full words, but we have to */
  143.         /* guarantee that they are word-aligned. */
  144.         switch (x & 3) {
  145.             case 3:
  146.             *pptr++ = (byte) cword;
  147.             case 2:
  148.             *pptr++ = (byte) cword;
  149.             case 1:
  150.             *pptr++ = (byte) cword;
  151.             case 0:;
  152.         }
  153.         /* Even with w = 5, we always store at least */
  154.         /* 3 full words, regardless of the starting x. */
  155.         *(bits32 *) pptr =
  156.             ((bits32 *) pptr)[1] =
  157.             ((bits32 *) pptr)[2] = cword;
  158.         pptr += 12;
  159.         while (pptr < limit) {
  160.             *(bits32 *) pptr =
  161.             ((bits32 *) pptr)[1] = cword;
  162.             pptr += 8;
  163.         }
  164.         switch ((int)(pptr - limit)) {
  165.             case 0:
  166.             pptr[6] = (byte) cword;
  167.             case 1:
  168.             pptr[5] = (byte) cword;
  169.             case 2:
  170.             pptr[4] = (byte) cword;
  171.             case 3:
  172.             *(bits32 *) pptr = cword;
  173.             break;
  174.             case 4:
  175.             pptr[2] = (byte) cword;
  176.             case 5:
  177.             pptr[1] = (byte) cword;
  178.             case 6:
  179.             pptr[0] = (byte) cword;
  180.             case 7:;
  181.         }
  182.         inc_ptr(dest, draster);
  183.         }
  184. #else
  185.         int bcnt = w * 3;
  186.  
  187.         INCR(fgray[min(w, 100)]);
  188.         while (h-- > 0) {
  189.         memset(dest, r, bcnt);
  190.         inc_ptr(dest, draster);
  191.         }
  192. #endif
  193.     } else {
  194.         int x3 = -x & 3, ww = w - x3;    /* we know ww >= 2 */
  195.         bits32 rgbr, gbrg, brgb;
  196.  
  197.         if (mdev->color24.rgb == color) {
  198.         rgbr = mdev->color24.rgbr;
  199.         gbrg = mdev->color24.gbrg;
  200.         brgb = mdev->color24.brgb;
  201.         } else {
  202.         INCR(fsetc);
  203.         set_color24_cache(color, r, g, b);
  204.         }
  205. #ifdef DEBUG
  206.         {
  207.         int ci;
  208.         for (ci = 0; ci < prev_count; ++ci)
  209.             if (prev_colors[ci] == color)
  210.             break;
  211.         INCR(fprevc[ci]);
  212.         if (ci == prev_count) {
  213.             if (ci < countof(prev_colors))
  214.             ++prev_count;
  215.             else
  216.             --ci;
  217.         }
  218.         if (ci) {
  219.             memmove(&prev_colors[1], &prev_colors[0],
  220.                 ci * sizeof(prev_colors[0]));
  221.             prev_colors[0] = color;
  222.         }
  223.         }
  224. #endif
  225.         INCR(fcolor[min(w, 100)]);
  226.         while (h-- > 0) {
  227.         register byte *pptr = dest;
  228.         int w1 = ww;
  229.  
  230.         switch (x3) {
  231.             case 1:
  232.             put3(pptr, r, g, b);
  233.             pptr += 3;
  234.             break;
  235.             case 2:
  236.             pptr[0] = r;
  237.             pptr[1] = g;
  238.             putw(pptr + 2, brgb);
  239.             pptr += 6;
  240.             break;
  241.             case 3:
  242.             pptr[0] = r;
  243.             putw(pptr + 1, gbrg);
  244.             putw(pptr + 5, brgb);
  245.             pptr += 9;
  246.             break;
  247.             case 0:
  248.             ;
  249.         }
  250. #ifdef USE_MEMCPY
  251.         /*
  252.          * For very wide fills, it's most efficient to fill a few
  253.          * pixels and then use memcpy to fill the rest.
  254.          */
  255.         if (w1 > 16) {
  256. #define PUTW4(ptr, w)\
  257.   BEGIN\
  258.     putw(ptr, w); putw((ptr)+12, w); putw((ptr)+24, w); putw((ptr)+36, w);\
  259.   END
  260.             PUTW4(pptr, rgbr);
  261.             PUTW4(pptr + 4, gbrg);
  262.             PUTW4(pptr + 8, brgb);
  263. #undef PUTW4
  264.             if (w1 > 64) {
  265.             memcpy(pptr + 48, pptr, 48);
  266.             memcpy(pptr + 96, pptr, 96);
  267.             for (pptr += 192; (w1 -= 64) >= 64; pptr += 192)
  268.                 memcpy(pptr, pptr - 192, 192);
  269.             } else
  270.             pptr += 48;
  271.             for (; (w1 -= 16) >= 16; pptr += 48)
  272.             memcpy(pptr, pptr - 48, 48);
  273.         }
  274. #endif
  275.         while (w1 >= 4) {
  276.             putw(pptr, rgbr);
  277.             putw(pptr + 4, gbrg);
  278.             putw(pptr + 8, brgb);
  279.             pptr += 12;
  280.             w1 -= 4;
  281.         }
  282.         switch (w1) {
  283.             case 1:
  284.             put3(pptr, r, g, b);
  285.             break;
  286.             case 2:
  287.             putw(pptr, rgbr);
  288.             pptr[4] = g;
  289.             pptr[5] = b;
  290.             break;
  291.             case 3:
  292.             putw(pptr, rgbr);
  293.             putw(pptr + 4, gbrg);
  294.             pptr[8] = b;
  295.             break;
  296.             case 0:
  297.             ;
  298.         }
  299.         inc_ptr(dest, draster);
  300.         }
  301.     }
  302.     } else if (h > 0) {        /* w < 5 */
  303.     INCR(fnarrow[max(w, 0)]);
  304.     setup_rect(dest);
  305.     switch (w) {
  306.         case 4:
  307.         do {
  308.             dest[9] = dest[6] = dest[3] = dest[0] = r;
  309.             dest[10] = dest[7] = dest[4] = dest[1] = g;
  310.             dest[11] = dest[8] = dest[5] = dest[2] = b;
  311.             inc_ptr(dest, draster);
  312.         }
  313.         while (--h);
  314.         break;
  315.         case 3:
  316.         do {
  317.             dest[6] = dest[3] = dest[0] = r;
  318.             dest[7] = dest[4] = dest[1] = g;
  319.             dest[8] = dest[5] = dest[2] = b;
  320.             inc_ptr(dest, draster);
  321.         }
  322.         while (--h);
  323.         break;
  324.         case 2:
  325.         do {
  326.             dest[3] = dest[0] = r;
  327.             dest[4] = dest[1] = g;
  328.             dest[5] = dest[2] = b;
  329.             inc_ptr(dest, draster);
  330.         }
  331.         while (--h);
  332.         break;
  333.         case 1:
  334.         do {
  335.             dest[0] = r, dest[1] = g, dest[2] = b;
  336.             inc_ptr(dest, draster);
  337.         }
  338.         while (--h);
  339.         break;
  340.         case 0:
  341.         default:
  342.         ;
  343.     }
  344.     }
  345.     return 0;
  346. }
  347.  
  348. /* Copy a monochrome bitmap. */
  349. private int
  350. mem_true24_copy_mono(gx_device * dev,
  351.            const byte * base, int sourcex, int sraster, gx_bitmap_id id,
  352.     int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
  353. {
  354.     gx_device_memory * const mdev = (gx_device_memory *)dev;
  355.     const byte *line;
  356.     int sbit;
  357.     int first_bit;
  358.  
  359.     declare_scan_ptr(dest);
  360.  
  361.     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
  362.     setup_rect(dest);
  363.     line = base + (sourcex >> 3);
  364.     sbit = sourcex & 7;
  365.     first_bit = 0x80 >> sbit;
  366.     if (zero != gx_no_color_index) {    /* Loop for halftones or inverted masks */
  367.     /* (never used). */
  368.     declare_unpack_color(r0, g0, b0, zero);
  369.     declare_unpack_color(r1, g1, b1, one);
  370.     while (h-- > 0) {
  371.         register byte *pptr = dest;
  372.         const byte *sptr = line;
  373.         register int sbyte = *sptr++;
  374.         register int bit = first_bit;
  375.         int count = w;
  376.  
  377.         do {
  378.         if (sbyte & bit) {
  379.             if (one != gx_no_color_index)
  380.             put3(pptr, r1, g1, b1);
  381.         } else
  382.             put3(pptr, r0, g0, b0);
  383.         pptr += 3;
  384.         if ((bit >>= 1) == 0)
  385.             bit = 0x80, sbyte = *sptr++;
  386.         }
  387.         while (--count > 0);
  388.         line += sraster;
  389.         inc_ptr(dest, draster);
  390.     }
  391.     } else if (one != gx_no_color_index) {    /* Loop for character and pattern masks. */
  392.     /* This is used heavily. */
  393.     declare_unpack_color(r1, g1, b1, one);
  394.     int first_mask = first_bit << 1;
  395.     int first_count, first_skip;
  396.  
  397.     if (sbit + w > 8)
  398.         first_mask -= 1,
  399.         first_count = 8 - sbit;
  400.     else
  401.         first_mask -= first_mask >> w,
  402.         first_count = w;
  403.     first_skip = first_count * 3;
  404.     while (h-- > 0) {
  405.         register byte *pptr = dest;
  406.         const byte *sptr = line;
  407.         register int sbyte = *sptr++ & first_mask;
  408.         int count = w - first_count;
  409.  
  410.         if (sbyte) {
  411.         register int bit = first_bit;
  412.  
  413.         do {
  414.             if (sbyte & bit)
  415.             put3(pptr, r1, g1, b1);
  416.             pptr += 3;
  417.         }
  418.         while ((bit >>= 1) & first_mask);
  419.         } else
  420.         pptr += first_skip;
  421.         while (count >= 8) {
  422.         sbyte = *sptr++;
  423.         if (sbyte & 0xf0) {
  424.             if (sbyte & 0x80)
  425.             put3(pptr, r1, g1, b1);
  426.             if (sbyte & 0x40)
  427.             put3(pptr + 3, r1, g1, b1);
  428.             if (sbyte & 0x20)
  429.             put3(pptr + 6, r1, g1, b1);
  430.             if (sbyte & 0x10)
  431.             put3(pptr + 9, r1, g1, b1);
  432.         }
  433.         if (sbyte & 0xf) {
  434.             if (sbyte & 8)
  435.             put3(pptr + 12, r1, g1, b1);
  436.             if (sbyte & 4)
  437.             put3(pptr + 15, r1, g1, b1);
  438.             if (sbyte & 2)
  439.             put3(pptr + 18, r1, g1, b1);
  440.             if (sbyte & 1)
  441.             put3(pptr + 21, r1, g1, b1);
  442.         }
  443.         pptr += 24;
  444.         count -= 8;
  445.         }
  446.         if (count > 0) {
  447.         register int bit = 0x80;
  448.  
  449.         sbyte = *sptr++;
  450.         do {
  451.             if (sbyte & bit)
  452.             put3(pptr, r1, g1, b1);
  453.             pptr += 3;
  454.             bit >>= 1;
  455.         }
  456.         while (--count > 0);
  457.         }
  458.         line += sraster;
  459.         inc_ptr(dest, draster);
  460.     }
  461.     }
  462.     return 0;
  463. }
  464.  
  465. /* Copy a color bitmap. */
  466. private int
  467. mem_true24_copy_color(gx_device * dev,
  468.            const byte * base, int sourcex, int sraster, gx_bitmap_id id,
  469.               int x, int y, int w, int h)
  470. {
  471.     gx_device_memory * const mdev = (gx_device_memory *)dev;
  472.  
  473.     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
  474.     mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
  475.     return 0;
  476. }
  477.  
  478. /* Copy an alpha map. */
  479. private int
  480. mem_true24_copy_alpha(gx_device * dev, const byte * base, int sourcex,
  481.            int sraster, gx_bitmap_id id, int x, int y, int w, int h,
  482.               gx_color_index color, int depth)
  483. {
  484.     gx_device_memory * const mdev = (gx_device_memory *)dev;
  485.     const byte *line;
  486.  
  487.     declare_scan_ptr(dest);
  488.     declare_unpack_color(r, g, b, color);
  489.  
  490.     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
  491.     setup_rect(dest);
  492.     line = base;
  493.     while (h-- > 0) {
  494.     register byte *pptr = dest;
  495.     int sx;
  496.  
  497.     for (sx = sourcex; sx < sourcex + w; ++sx, pptr += 3) {
  498.         int alpha2, alpha;
  499.  
  500.         if (depth == 2)    /* map 0 - 3 to 0 - 15 */
  501.         alpha =
  502.             ((line[sx >> 2] >> ((3 - (sx & 3)) << 1)) & 3) * 5;
  503.         else
  504.         alpha2 = line[sx >> 1],
  505.             alpha = (sx & 1 ? alpha2 & 0xf : alpha2 >> 4);
  506.         if (alpha == 15) {    /* Just write the new color. */
  507.         put3(pptr, r, g, b);
  508.         } else if (alpha != 0) {    /* Blend RGB values. */
  509. #define make_shade(old, clr, alpha, amax) \
  510.   (old) + (((int)(clr) - (int)(old)) * (alpha) / (amax))
  511.         pptr[0] = make_shade(pptr[0], r, alpha, 15);
  512.         pptr[1] = make_shade(pptr[1], g, alpha, 15);
  513.         pptr[2] = make_shade(pptr[2], b, alpha, 15);
  514. #undef make_shade
  515.         }
  516.     }
  517.     line += sraster;
  518.     inc_ptr(dest, draster);
  519.     }
  520.     return 0;
  521. }
  522.  
  523. /* ================ "Word"-oriented device ================ */
  524.  
  525. /* Note that on a big-endian machine, this is the same as the */
  526. /* standard byte-oriented-device. */
  527.  
  528. #if !arch_is_big_endian
  529.  
  530. /* Procedures */
  531. declare_mem_procs(mem24_word_copy_mono, mem24_word_copy_color, mem24_word_fill_rectangle);
  532.  
  533. /* Here is the device descriptor. */
  534. const gx_device_memory mem_true24_word_device =
  535. mem_full_device("image24w", 24, 0, mem_open,
  536.         gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
  537.      mem24_word_copy_mono, mem24_word_copy_color, mem24_word_fill_rectangle,
  538.         gx_default_map_cmyk_color, gx_default_strip_tile_rectangle,
  539.         gx_no_strip_copy_rop, mem_word_get_bits_rectangle);
  540.  
  541. /* Fill a rectangle with a color. */
  542. private int
  543. mem24_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
  544.               gx_color_index color)
  545. {
  546.     gx_device_memory * const mdev = (gx_device_memory *)dev;
  547.     byte *base;
  548.     uint raster;
  549.  
  550.     fit_fill(dev, x, y, w, h);
  551.     base = scan_line_base(mdev, y);
  552.     raster = mdev->raster;
  553.     mem_swap_byte_rect(base, raster, x * 24, w * 24, h, true);
  554.     mem_true24_fill_rectangle(dev, x, y, w, h, color);
  555.     mem_swap_byte_rect(base, raster, x * 24, w * 24, h, false);
  556.     return 0;
  557. }
  558.  
  559. /* Copy a bitmap. */
  560. private int
  561. mem24_word_copy_mono(gx_device * dev,
  562.            const byte * base, int sourcex, int sraster, gx_bitmap_id id,
  563.     int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
  564. {
  565.     gx_device_memory * const mdev = (gx_device_memory *)dev;
  566.     byte *row;
  567.     uint raster;
  568.     bool store;
  569.  
  570.     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
  571.     row = scan_line_base(mdev, y);
  572.     raster = mdev->raster;
  573.     store = (zero != gx_no_color_index && one != gx_no_color_index);
  574.     mem_swap_byte_rect(row, raster, x * 24, w * 24, h, store);
  575.     mem_true24_copy_mono(dev, base, sourcex, sraster, id,
  576.              x, y, w, h, zero, one);
  577.     mem_swap_byte_rect(row, raster, x * 24, w * 24, h, false);
  578.     return 0;
  579. }
  580.  
  581. /* Copy a color bitmap. */
  582. private int
  583. mem24_word_copy_color(gx_device * dev,
  584.            const byte * base, int sourcex, int sraster, gx_bitmap_id id,
  585.               int x, int y, int w, int h)
  586. {
  587.     gx_device_memory * const mdev = (gx_device_memory *)dev;
  588.     byte *row;
  589.     uint raster;
  590.  
  591.     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
  592.     row = scan_line_base(mdev, y);
  593.     raster = mdev->raster;
  594.     mem_swap_byte_rect(row, raster, x * 24, w * 24, h, true);
  595.     bytes_copy_rectangle(row + x * 3, raster, base + sourcex * 3, sraster,
  596.              w * 3, h);
  597.     mem_swap_byte_rect(row, raster, x * 24, w * 24, h, false);
  598.     return 0;
  599. }
  600.  
  601. #endif /* !arch_is_big_endian */
  602.